<!doctype html>
<html>
    <head>
        <title>编辑交互手册 - HT for Web</title>
        <meta charset="UTF-8">    
        <meta name="viewport" content="user-scalable=yes, width=1024">
        <style type="text/css"> 
            h1, h2, h3, h4, h5, h6, p, blockquote {
                margin: 0;
                padding: 0;
            }
            body {
                font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", Arial, sans-serif;
                font-size: 13px;
                line-height: 18px;
                color: #737373;
                background-color: white; 
                margin: 10px 13px 10px 13px;
            }
            table {
                margin: 10px 0 15px 0;
                border-collapse: collapse;
            }
            td,th {	
                border: 1px solid #ddd;
                padding: 3px 10px;
            }
            th {
                padding: 5px 10px;	
            }
            a {
                color: #0069d6;
            }
            a:hover {
                color: #0050a3;
                text-decoration: none;
            }
            a img {
                border: none;
            }
            p {
                margin-bottom: 9px;
            }
            h1, h2, h3, h4, h5, h6 {
                color: #404040;
                line-height: 36px;
            }
            h1 {
                margin-bottom: 18px;
                font-size: 30px;
            }
            h2 {
                font-size: 24px;
            }
            h3 {
                font-size: 18px;
            }
            h4 {
                font-size: 16px;
            }
            h5 {
                font-size: 14px;
            }
            h6 {
                font-size: 13px;
            }
            hr {
                margin: 0 0 19px;
                border: 0;
                border-bottom: 1px solid #ccc;
            }
            blockquote {
                padding: 13px 13px 21px 15px;
                margin-bottom: 18px;
                font-family:georgia,serif;
                font-style: italic;
            }
            blockquote:before {
                content:"\201C";
                font-size:40px;
                margin-left:-10px;
                font-family:georgia,serif;
                color:#eee;
            }
            blockquote p {
                font-size: 14px;
                font-weight: 300;
                line-height: 18px;
                margin-bottom: 0;
                font-style: italic;
            }
            code, pre {
                font-family: Monaco, Andale Mono, Courier New, monospace;
            }
            code {
                background-color: #fee9cc;
                color: rgba(0, 0, 0, 0.75);
                padding: 1px 3px;
                font-size: 12px;
                -webkit-border-radius: 3px;
                -moz-border-radius: 3px;
                border-radius: 3px;
            }
            pre {
                display: block;
                padding: 14px;
                margin: 0 0 18px;
                line-height: 16px;
                font-size: 11px;
                border: 1px solid #d9d9d9;
                white-space: pre-wrap;
                word-wrap: break-word;
            }
            pre code {
                background-color: #fff;
                color:#737373;
                font-size: 11px;
                padding: 0;
            }
            sup {
                font-size: 0.83em;
                vertical-align: super;
                line-height: 0;
            }
            * {
                -webkit-print-color-adjust: exact;
            }
            @media screen and (min-width: 914px) {
                body {
                    width: 854px;
                    margin:10px auto;
                }
            }
            @media print {
                body,code,pre code,h1,h2,h3,h4,h5,h6 {
                    color: black;
                }
                table, pre {
                    page-break-inside: avoid;
                }
            }                        
            iframe{
                width: 100%;
                border: 1px solid #34495E;
                margin: 0;                
            }            
            .logo{
                vertical-align: middle;
            }

        </style>        
        <script>
            function init() {
                var logoSrc = '',
                    logos = document.querySelectorAll('.logo'),
                    i = 0;
                for (; i < logos.length; i++) {
                    logos[i].src = logoSrc;
                }
                
                var iframes = document.querySelectorAll('iframe'),
                    func = function(){};
                for (i=0; i < iframes.length; i++) {
                    var iframe = iframes[i];
                    
                    // a small hack to make it work on android
                    iframe.ontouchstart = func;
                    
                    var div = document.createElement('div');
                    div.innerHTML = '<a href="' + iframe.src + '" target="_blank">独立运行→</a>';
                    iframe.parentNode.insertBefore(div, iframe);
                }   
            }
        </script>    
    </head>
    <body onload="init();">
        <a href="http://www.hightopo.com"><img class="logo"></a>HT for Web 编辑交互手册
        <hr style="margin: 1px 0 20px 0">
<p>索引</p>

<ul><li><a href="#ref_description">概述</a></li><li><a href="#ref_demo">实例</a></li><li><a href="#ref_customstyle">自定义外观样式</a></li><li><a href="#ref_custombehavior">自定义行为</a></li><li><a href="#ref_snaptogrid">网格吸附</a></li><li><a href="#ref_3d">辅助3D编辑</a></li></ul>

<hr/>

<div id="ref_description"></div>

<h3>概述</h3>

<p><code>HT</code>产品包自带<code>ht.graph.EditInterctor</code>，可以完成简单的编辑功能，但是也有一些限制，比如无法完成旋转后再编辑等功能。
此插件是对<code>ht.graph.EditInterctor</code>的补充，适用于复杂编辑的场景，主要优点如下：</p>

<ul><li>编辑控制点保持固定大小</li><li>节点旋转后可编辑大小</li><li>可将节点分组并旋转和编辑大小</li><li>美化编辑效果，支持<code>API</code>自定义丰富的编辑样式</li><li>支持自定义行为，包括：网格吸附、<code>Shape</code>点吸附、角度捕获、按比例编辑大小</li><li>支持改变<code>Shape</code>的线段类型</li><li>控制<code>Shape</code>是否闭合</li><li>辅助编辑3D场景中的高度</li><li>支持多种辅助编辑器，快速改变图元之间的<code>host</code>和<code>parent</code>关系，甚至是创建连线、改变连线的端点，改变<code>host</code>时支持吸附到<code>Grid</code>单元格和<code>CSGShape</code>的线段</li></ul>

<p>要使用此插件，您的页面里需要引入相关的<code>js</code>文件：</p>

<pre><code>&lt;script src=&quot;ht.js&quot;&gt;&lt;/script&gt; &lt;!--先引入ht.js--&gt;
&lt;script src=&quot;ht-xeditinteractor.js&quot;&gt;&lt;/script&gt;</code></pre>

<p>然后创建此交互的实例，并设置到拓扑组件上：</p>

<pre><code>var editInteractor = new ht.graph.XEditInteractor(graph);
graph.setInteractors(new ht.List([
    new ht.graph.ScrollBarInteractor(graph),
    new ht.graph.SelectInteractor(graph),
    editInteractor,
    new ht.graph.MoveInteractor(graph),
    new ht.graph.DefaultInteractor(graph),
    new ht.graph.TouchInteractor(graph , {editable: false})//禁用Touch上默认的编辑功能
]));</code></pre>

<p>也可以使用下面简单的方式：</p>

<pre><code>graph.setEditable(true);</code></pre>

<p><code>HT</code>内部自动判断，如果引入了此插件，使用此插件作为编辑交互器，否则使用自带的编辑交互</p>

<p>此交互提供了六种<code>辅助编辑按钮</code>，在辅助编辑按钮上按下鼠标并拖拽到另一个图元上(除删除之外)，即可改变<code>host</code>、<code>parent</code>关系或创建连线或改变连线端点；拖拽到空白区域可以打断关系</p>

<ul><li><img alt="host" src="examples/res/host.jpeg"/> <code>host</code>按钮，设置<code>host</code>吸附关系，当目标是<code>Grid</code>时支持吸附到单元格中，当目标时<code>CSGShape</code>时支持吸附到线段上</li><li><img alt="parent" src="examples/res/parent.jpeg"/> <code>parent</code>按钮，设置<code>parent</code>父子关系</li><li><img alt="edge" src="examples/res/edge.jpeg"/> <code>edge</code>按钮，创建<code>Edge</code>，可重写交互对象的<code>onEdgeCreated(e, edge)</code>方法，对创建完的<code>Edge</code>设置特殊样式</li><li><img alt="remove" src="examples/res/remove.jpeg"/> <code>remove</code>按钮，通过双击操作删除当前图元</li><li><img alt="source" src="examples/res/source.jpeg"/> <code>source</code>按钮，改变连线的<code>Source</code></li><li><img alt="target" src="examples/res/target.jpeg"/> <code>target</code>按钮，改变连线的<code>Target</code></li><li><img alt="tall" src="examples/res/tall.jpeg"/> <code>tall</code>按钮，调整3D场景中模型的高度(Y轴高度)</li><li><img alt="elevation" src="examples/res/elevation.jpeg"/> <code>elevation</code>或<code>pointElevation</code>按钮，调整3D场景中模型或点的海拔(Y轴坐标)</li></ul>

<p>可以重载 <code>getHelperCursor(helper)</code> 方法，自定义按钮的鼠标手势，<code>helper</code> 参数对应的是前面提到的按钮名称</p>

<p>关于交互的详细信息可参考<code>beginners guide</code>文档中的<code>交互</code>章节</p>

<div id="ref_demo"></div>

<h3>实例</h3>

<p>您可以操作下面的实例验证此插件：</p>

<p><iframe src="examples/example_demo.html" style="height:250px"></iframe></p>

<p>此插件提供了一些<code>API</code>操作<code>Shape</code>，列举如下：</p>

<ul><li><code>changeShapeSegment(shape, segmentIndex, newSegmentType)</code>将<code>shape</code>的序号为<code>segmentIndex</code>的线段改为<code>newSegmentType</code>类型。
另外在和右键菜配合使用时，可以在线段上点击右键然后调用此接口，只传入<code>newSegmentType</code>即可，此插件可以自动识别<code>shape</code>和<code>segmentIndex</code></li><li><code>addShapePoint(shape, segmentIndex, newPoint)</code>在<code>shape</code>的序号为<code>segmentIndex</code>的线段上增加新点<code>newPoint</code>，并自动调整剩下的点和线段类型。
在和右键菜单配合使用时，可以在线段上点击右键然后调用此接口，无需传入参数，此插件会把点击的坐标当作<code>newPoint</code>，插入到相应的线段上</li><li><code>removeShapePoint(shape, pointIndex)</code>删除<code>shape</code>的序号为<code>pointIndex</code>的点，并自动调整剩下的点和线段类型。
在和右键菜单配合使用时，可以在相应的点上点击右键然后调用此接口，无需传入参数，此插件自动识别<code>shape</code>和<code>pointIndex</code></li><li><code>getDefaultSegments(data)</code> <code>Shape</code>或<code>Edge</code>的<code>segments</code>为空时，可用此方法得到默认的<code>segments</code></li><li><code>_shape</code> 鼠标下有高亮线段或编辑点时，高亮线段或编辑点所属的<code>Shape</code></li><li><code>_edge</code> 鼠标下有高亮线段或编辑点时，高亮线段或编辑点所属的<code>Edge</code></li><li><code>_hoverSegmentIndex</code> 鼠标下高亮线段的下标</li><li><code>_pause</code> 为<code>true</code>时交互内部停止检测鼠标位置，右键菜单显示出来以后应该设为<code>true</code>，避免再改变<code>_hoverSegmentIndex</code>，右键菜单隐藏后再设回<code>false</code></li><li><code>onEdgeCreated(e, edge)</code> 通过辅助编辑按钮创建连线时，此方法被回调，可以重写此方法对创建的连线设置样式</li></ul>

<div id="ref_customstyle"></div>

<h4>自定义外观样式</h4>

<p>此插件在拓扑组件(<code>ht.graph.GraphView</code>)上注入了一些<code>API</code>用于控制编辑外观，列举如下：</p>

<ul><li><code>editRectBorderColor</code>属性通过<code>getEditRectBorderColor()</code>和<code>setEditRectBorderColor(&#39;newColor&#39;)</code>操作，表示编辑框的边框颜色，默认值为<code>rgb(0, 168, 255)</code></li><li><code>editRectBorderStyle</code>属性通过<code>getEditRectBorderStyle()</code>和<code>setEditRectBorderStyle(&#39;newStyle&#39;)</code>操作，表示编辑框的边框样式，可选值如下：<ul><li><code>solid</code> 实线边框</li><li><code>dashed</code> 虚线边框，此为默认值(需要使用<code>Chrome</code>或<code>Firefox</code>或<code>IE11</code>)</li></ul></li><li><code>editRectPadding</code>属性通过<code>getEditRectPadding()</code>和<code>setEditRectPadding(newPadding)</code> 操作，表示编辑框与节点边缘的间距，默认值为<code>6</code></li><li><code>nodeBorderColor</code>属性通过<code>getNodeBorderColor()</code>和<code>setNodeBorderColor(&#39;newColor&#39;)</code>操作，表示组内被选中的节点的边框颜色，默认值为<code>#1ABC9C</code></li><li><code>editPointBackground</code>属性通过<code>getEditPointBackground()</code>和<code>setEditPointBackground(&#39;newColor&#39;)</code>操作，表示编辑点的背景色，编辑点包括编辑大小控制点，<code>Shape</code>连接点及旋转控制点，默认值为<code>#E2E2E2</code></li><li><code>editPointBorderColor</code>属性通过<code>getEditPointBorderColor()</code>和<code>setEditPointBorderColor(&#39;newColor&#39;)</code>操作，表示编辑点的边框色，编辑点包括编辑大小控制点，<code>Shape</code>连接点及旋转控制点，默认值为<code>#2C3E50</code></li><li><code>editPointSize</code>属性通过<code>getEditPointSize()</code>和<code>setEditPointSize(newSize)</code>操作，表示编辑点的大小，编辑点包括编辑大小控制点，<code>Shape</code>连接点、控制点及旋转控制点，默认值为<code>9</code></li><li><code>joinPointBackground</code>属性通过<code>getJoinPointBackground()</code>和<code>setJoinPointBackground(&#39;newColor&#39;)</code>操作，表示<code>Shape</code>连接点的背景色，优先级高于<code>editPointBackground</code>，如果为空则取<code>editPointBackground</code>的颜色，默认为空</li><li><code>joinPointBorderColor</code>属性通过<code>getJoinPointBorderColor()</code>和<code>setJoinPointBorderColor(&#39;newColor&#39;)</code>操作，表示<code>Shape</code>连接点的边框色，优先级高于<code>editPointBorderColor</code>，如果为空则取<code>editPointBorderColor</code>的颜色，默认为空</li><li><code>controlPointBackground</code>属性通过<code>getControlPointBackground()</code>和<code>setControlPointBackground(&#39;newColor&#39;)</code>操作，表示<code>Shape</code>控制点的背景色，默认为<code>#ff0</code></li><li><code>controlPointBorderColor</code>属性通过<code>getControlPointBorderColor()</code>和<code>setControlPointBorderColor(&#39;newColor&#39;)</code>操作，表示<code>Shape</code>控制点的边框色，默认与<code>editPointBorderColor</code>保持一致</li><li><code>snapPointBorderColor</code>属性通过<code>getSnapPointBorderColor()</code>和<code>setSnapPointBorderColor(&#39;newColor&#39;)</code>操作，表示<code>Shape</code>吸附点的边框色，默认值为<code>#f00</code></li><li><code>directionLineColor</code>属性通过<code>getDirectionLineColor()</code>和<code>setDirectionLineColor(&#39;newColor&#39;)</code>操作，表示<code>Shape</code>指导线的颜色，默认值为<code>#888</code></li><li><code>segmentHoverColor</code>属性通过<code>getSegmentHoverColor()</code>和<code>setSegmentHoverColor(&#39;newColor&#39;)</code>操作，表示<code>Shape</code>线段<code>hover</code>时的颜色，默认值为<code>rgba(255, 0, 0, 0.3)</code></li><li><code>segmentHoverWidth</code>属性通过<code>getSegmentHoverWidth()</code>和<code>setSegmentHoverWidth(newWidth)</code>操作，表示<code>Shape</code>线段<code>hover</code>时的宽度，默认值为<code>8</code></li><li><code>editHelperSize</code> 通过<code>getEditHelperSize()</code>和<code>setEditHelperSize(size)</code>操作，表示辅助编辑按钮的大小，默认为<code>16</code></li><li><p><code>helperEditableFunc</code> 通过<code>getHelperEditableFunc()</code>和<code>setHelperEditableFunc(func)</code>操作，设置辅助编辑功能是否可用的过滤器，假如要关闭<code>host</code>辅助编辑但保留<code>parent</code>辅助编辑，可以通过以下代码实现：</p><pre><code>graphView.setHelperEditableFunc(function(data, helper) {
    if (helper === &#39;host&#39;) {
        return false;
    }
    return true;
});</code></pre></li><li><p><code>leftTopHelpers</code>通过<code>getLeftTopHelpers()</code>和<code>setLeftTopHelpers(helpers)</code>操作，控制左上角的辅助按钮，数组类型，默认为<code>[&#39;parent&#39;]</code></p></li><li><code>rightTopHelpers</code>通过<code>getRightTopHelpers()</code>和<code>setRightTopHelpers(helpers)</code>操作，控制右上角的辅助按钮，数组类型，默认为<code>[&#39;host&#39;]</code></li><li><code>leftBottomHelpers</code>通过<code>getLeftBottomHelpers()</code>和<code>setLeftBottomHelpers(helpers)</code>操作，控制左下角的辅助按钮，数组类型，默认为<code>[&#39;edge&#39;]</code></li><li><code>rightBottomHelpers</code>通过<code>getRightBottomHelpers()</code>和<code>setRightBottomHelpers(helpers)</code>操作，控制右下角的辅助按钮，数组类型，默认为<code>[&#39;remove&#39;]</code></li><li><code>leftTopHelpersAlign</code>通过<code>getLeftTopHelpersAlign()</code>和<code>setLeftTopHelpersAlign(align)</code>操作，控制左上角的辅助按钮的对齐方式，默认为<code>h</code>水平对齐，可改为<code>v</code>垂直对齐</li><li><code>rightTopHelpersAlign</code>通过<code>getRightTopHelpersAlign()</code>和<code>setRightTopHelpersAlign(align)</code>操作，控制右上角的辅助按钮的对齐方式，默认为<code>h</code>水平对齐，可改为<code>v</code>垂直对齐</li><li><code>leftBottomHelpersAlign</code>通过<code>getLeftBottomHelpersAlign()</code>和<code>setLeftBottomHelpersAlign(align)</code>操作，控制左下角的辅助按钮的对齐方式，默认为<code>h</code>水平对齐，可改为<code>v</code>垂直对齐</li><li><code>rightBottomHelpersAlign</code>通过<code>getRightBottomHelpersAlign()</code>和<code>setRightBottomHelpersAlign(align)</code>操作，控制右下角的辅助按钮的对齐方式，默认为<code>h</code>水平对齐，可改为<code>v</code>垂直对齐</li></ul>

<p>上面一些概念的图示如下：</p>

<p><img alt="概念图示" src="examples/res/desc.jpeg"/></p>

<div id="ref_custombehavior"></div>

<h4>自定义行为</h4>

<p>此插件在拓扑组件(<code>ht.graph.GraphView</code>)上注入了一些<code>API</code>用于控制编辑行为，列举如下：</p>

<ul><li><code>resizeMode</code>属性通过<code>getResizeMode()</code>和<code>setResizeMode(&#39;newMode&#39;)</code>操作，表示左上、左下，右上，右下四个编辑点的编辑模式，可选值如下：<ul><li><code>normal</code> 可任意编辑，此为默认值</li><li><code>keepRatio</code> 编辑时保持宽高比</li></ul></li><li><code>snapAngle</code>属性通过<code>getSnapAngle()</code>和<code>setSnapAngle(newAngle)</code> 操作，表示捕获角度，单位为弧度，默认值为<code>Math.PI / 36</code>即角度制<code>5</code>度</li><li><code>snapSpacing</code>属性通过<code>getSnapSpacing()</code>和<code>setSnapSpacing(newSpacing)</code>操作，表示编辑大小时要吸附的尺寸，默认为空，表示不吸附</li><li><code>pointSnapSpacing</code>属性通过<code>getPointSnapSpacing()</code>和<code>setPointSnapSpacing(newSpacing)</code>操作，表示编辑时<code>edge</code>和<code>shape</code>的点要吸附的尺寸，默认为空，表示不吸附</li></ul>

<p>除了上面三个属性，此插件也支持<code>HT</code>内部的编辑、旋转过滤器，可以精细控制节点是否可编辑旋转等，过滤器的内容可参考<code>beginners guide</code>文档中的<code>过滤</code>章节</p>

<div id="ref_snaptogrid"></div>

<h4>网格吸附</h4>

<p>下面的例子展示如何使用此插件实现网格吸附功能：</p>

<p><iframe src="examples/example_snaptogrid.html" style="height:250px"></iframe></p>

<p>此插件可以实现编辑时的吸附功能，绘制网格背景和移动吸附需要额外编码实现。
在这个例子中，网格背景采用<code>painter</code>机制实现，移动吸附通过自定义的<code>SnapMoveInteractor</code>实现。</p>

<div id="ref_3d"></div>

<h4>辅助3D编辑</h4>

<p><code>3D</code>编辑是一个非常复杂的命题，除了<code>Graph3dView</code>提供的九段式编辑，此插件也提供了<code>elevation</code>、<code>pointElevatoin</code>、<code>tall</code>三个辅助按钮编辑<code>3D</code>模型的海拔(Y轴坐标)、点海拔(<code>Shape</code>或<code>Edge</code>点的Y轴坐标)和模型高度(Y轴尺寸)，请参考下面的例子：</p>

<p><iframe src="examples/example_helpers.html" style="height:650px"></iframe></p>    <hr id="contact" style="margin: 20px 0 1px 0">
    <a href="http://www.hightopo.com"><img class="logo"></a>欢迎交流 <a href="mailto:service@hightopo.com">service@hightopo.com</a>
</body>
</html>
